package abacab.agent.actor;

import abacab.utils.SimpleLinkedQueue;

/**
 * Represents an object shared by multiple actors
 * 
 * @param <T>
 *          the type of the object
 */
@SuppressWarnings("rawtypes")
public class SharedObject<T> {
	/** The shared object */
	private final T													object;

	/** The agents waiting for the lock */
	private final SimpleLinkedQueue<Agent>	queuedAgents;

	/** The agent currently holding the lock */
	private Agent														lockingAgent;

	/**
	 * Create the shared object
	 * 
	 * @param object
	 *          the object
	 */
	public SharedObject(T object) {
		this.object = object;
		this.queuedAgents = new SimpleLinkedQueue<Agent>();
	}

	/**
	 * @return the object
	 */
	public T get() {
		return this.object;
	}

	/**
	 * Take the lock on the object
	 * 
	 * @param agent
	 *          the agent
	 * @return 1 if the agent got the lock, 0 otherwise
	 */
	public int lock(Agent agent) {
		if (this.lockingAgent == null) {
			this.lockingAgent = agent;
			return 1;
		}
		this.queuedAgents.offer(agent);
		return 0;
	}

	/**
	 * Unlock the lock
	 */
	public void unlock() {
		Agent agent = this.queuedAgents.poll();
		if (agent != null) {
			this.lockingAgent = agent;
			agent.lockAcquired();
		}
		else {
			this.lockingAgent = null;
		}
	}
}